<?php
/**
 * Created by PhpStorm.
 *
 * @Date: 2017-08-01
 * @Time: 12:08
 * @Author: cdkay
 * @Email: network@iyuanma.net
 *
 * @File： Users.php
 */
namespace app\api\model\user;

use app\api\controller\User;
use app\common\model\AgencySalesman;
use app\common\model\Chat;
use app\common\lib\rongcloud\RongCloud;
use app\common\model\ApiResponse;
use app\common\model\UserCreditRecord;
use app\common\model\UserNoticeMessage;
use app\common\model\zds\Customer;
use Curl\Curl;
use library\IntConvert;
use think\Cache;
use think\Db;
use think\db\Query;
use think\Env;
use think\Exception;
use think\Log;
use think\Model;
use think\Request;
use think\Validate;

/**
 * Class Users
 * @package app\api\model\user
 *
 * @property integer id
 * @property string mobile
 * @property string password
 * @property string nickname
 * @property string realname
 * @property string avatar
 * @property integer credit
 * @property integer invite_credit
 * @property integer regtime
 * @property integer level
 * @property integer gender
 * @property string openid
 * @property string register_from
 *
 * @property integer admin_id
 * @property string extension_code
 *
 */
class Users extends Model {
    protected $table = 'users';
    protected $pk = 'id';

    private static $SaveFields = ['mobile','password','nickname','avatar','credit','invite_credit','regtime','level','gender','vip','register_from'];
    public static function getSaveFields(): array {
        return self::$SaveFields;
    }

    const REGISTER_FROM_CLIENT          = 1;
    const REGISTER_FROM_SALES_VIP       = 2;
    const REGISTER_FROM_SCRIPT_IMPORT   = 3;
    const REGISTER_FROM_IOS_TOURIST     = 4;
    const REGISTER_FROM_ADMIN           = 5;
    public static $RegisterFromSources = [
        self::REGISTER_FROM_CLIENT          => '客户端',
        self::REGISTER_FROM_SALES_VIP       => '销售系统',
        self::REGISTER_FROM_SCRIPT_IMPORT   => '脚本导入',
        self::REGISTER_FROM_IOS_TOURIST     => 'ios游客',
        self::REGISTER_FROM_ADMIN           => '管理员添加',
    ];


    public static $UserLevels = [
        '1'=> '小白',
        '2'=> '韭菜',
        '3'=> '菜鸟',
        '4'=> '老手',
        '5'=> '专家',
        '6'=> '大神',
    ];
    public static function getUserLevelName($level) {
        return self::$UserLevels[$level] ?? '';
    }

    /**
     * query_user_exist
     * 查询用户是否已经存在
     *
     * @author zhengkai
     * @date 2017-08-01
     *
     * @param string $mobile 手机号码
     * @return bool
     */
    public function query_user_exist($mobile)
    {
        return $this->where('mobile', $mobile)->count('id');
    }

    /**
     * @param $mobile
     * @return boolean
     */
    public static function exists($mobile) {
        $sql = <<<SQL
SELECT exists(
SELECT * FROM users WHERE mobile=:mobile LIMIT 1
) e
SQL;
        $re = Db::query($sql, ['mobile' => $mobile]);
        return $re[0]['e'];
    }

    /**
     * modify_invite_user_once
     * 修改绑定的推广员，只能修改一次
     *
     * @param $user
     * @param $invite_code
     * @return string
     */
    public static function modify_invite_user_once($user, $invite_code) {

        $user = self::get($user['id']);
        if ($user['promoter_id']) {
            $parentUser = self::get(['id'=>$user['promoter_id']]);
            return $parentUser['extension_code'];
        } else {
            $parentUser = self::get(['extension_code'=>$invite_code]);

            if (!$parentUser) return false;
            if($parentUser['id']==$user['id']) return false;
            $re = self::where('id', $user['id'])->update([
                'promoter_id' => $parentUser['id']
            ]);
            if ($re) {
                $credit = Users::creditTask($parentUser['id'],UserCreditRecord::CHANGE_TYPE_INVITE_USER);
                UserNoticeMessage::sendInviteRegisterMessage($parentUser['id'], $user['mobile'], $credit);
            }

            return $parentUser['extension_code'];
        }
    }

    /**
     * 查询用户被绑定的邀请码
     *
     * @param $userid
     * @return mixed|string
     */
    public static function get_user_invited_code($userid) {
        $re = self::get($userid);

        $promoter_id = $re->promoter_id?:0;

        $re = self::get(['id'=>$promoter_id]);

        return $re->extension_code ?? '';
    }

    /**
     * query_agency_info
     * 根据推广员邀请码查询推广员信息
     *
     * @author zhengkai
     * @date 2017-08-22
     *
     * @todo v1.4.1废弃
     *
     * @param int $code 推广员邀请码
     * @return \think\response\Json|false
     */
    public function query_agency_info($code)
    {
        $result = Db::table('agency_salesman')
           ->where('code', $code)
           ->find();
       // if (!empty($result) && !is_array($result)) {
       if ($result) {
           return $result;
       } else {
           return false;
       }
    }

    /**
     * create_user
     * 创建新用户
     *
     * @author zhengkai
     * @date 2017-08-01
     *
     * @param string $mobile 手机号码
     * @param string $realname 用户真实姓名
     * @param int $register_from
     * @return false|int
     */
    public function create_user($mobile, $realname='', $register_from = self::REGISTER_FROM_CLIENT)
    {
        $data = [
            'mobile' => $mobile,
            'regtime' => time(),
            'realname' => $realname,
            'register_from' => $register_from,
        ];

        $this->data($data)->save();

        return (int)$this->getLastInsID();
    }

    /**
     * @param $mobile
     * @param $password
     * @param null $realname
     * @param null $nickname
     * @param int $registerFrom
     * @return static
     */
    public static function addUserIfNonExists($mobile, $password, $realname = null, $nickname = null, $registerFrom = self::REGISTER_FROM_CLIENT) {
        $user = self::get(['mobile' => $mobile]);
        if (empty($user)) {
            $user = new static();
            $user->mobile = $mobile;
            $user->password = $password;
            if (null !== $realname) $user->realname;
            if (null !== $nickname) $user->nickname;
            $user->register_from = $registerFrom;
            $user->save();
            self::set_user_ability($user->id);
        }
        return $user;
    }

    /**
     * * get_user_single
     * 获取单条用户数据
     *
     * @author zhengkai
     * @date 2017-08-01
     *
     * @param array $field 查询字段
     *      id 用户id
     *      mobile 手机号码
     * @return array|bool|false|\PDOStatement|string|Model
     */
    public function get_user_single($field)
    {
        if (array_key_exists('id', $field)) $this->where('id', $field['id']);
        if (array_key_exists('mobile', $field)) $this->where('mobile', $field['mobile']);
        $result = $this->find();

        if (empty($result) && !is_array($result) && !count($result)) return false;

        return $result;
    }

    /**
     * 获取用户信息
     *
     * @param $uid
     * @return mixed|\stdClass
     */
    public static function info($uid) {
        $sql = <<<SQL
select 
id as uid,
mobile,
nickname,
avatar,
gender,
credit,
openid,
promoter_id,
extension_code as agency_code
from users where id=:uid
SQL;
        $data = Db::query($sql, ['uid'=>$uid]);
        $data = $data[0];

        $data['avatar'] = $data['avatar']?:Users::defaultAvatar();
        $data['nickname'] = ($data['nickname']?:mobile_hidden(substr($data['mobile'], 0, 11)))?:$data['uid'];

        if (!empty($data['promoter_id']) && $data['promoter_id']) {
            $parentUser = self::get(['id'=>$data['promoter_id']]);
            $data['agency_invite_code'] = $parentUser->extension_code;
        } else {
            $data['agency_invite_code'] = '';
        }
        $data['invite_url'] = $data['agency_code']?AgencySalesman::getInviteUrl($data['agency_code']):'';

        $data['is_vip'] = Customer::is_vip($uid); // 是否为vip用户

        $data['token'] = Cache::tag('user_token')->get('user_'.$uid);

        // 检查用户的聊天服务器token，获取融云聊天服务器token
        $data['chat'] = self::chatToken((new self())->get_user_single(['mobile'=> $data['mobile']]));

        return $data;
    }

    /**
     * 获取默认头像方法
     *
     * @return string
     */
    public static function defaultAvatar() {
        return Env::get('server.defaultAvatar');
    }

    /**
     * 获取聊天服务器的id和token
     *
     * @param $ud
     * @param bool $throw_error
     * @return array|mixed
     */
    public static function chatToken($ud, $throw_error = false) {

        if ($ud instanceof Users) $ud = $ud->toArray();
        elseif ($ud instanceof \stdClass) $ud = (array)$ud;

        $chatId = Chat::getChatId('u'.$ud['id']);
        $chat = Chat::cache($chatId);

        $name = (!empty($ud['nickname'])?$ud['nickname']:mobile_hidden(substr($ud['mobile'], 0, 11)))?:$ud['id'];
        $avatar = $ud['avatar']?:self::defaultAvatar();

        if ($chat) {
            $chat['name'] = $name;
            $chat['avatar'] = $avatar;
            return $chat;
        }

        try{
            $rong = RongCloud::getInstance();
            $re = $rong->User()->getToken($chatId, $name, $avatar);
            $chat_token = $re['token'] ?? null;

            $chat = [
                'id' => $chatId,
                'name' => $name,
                'avatar' => $avatar,
                'token' => $chat_token,
            ];
            Chat::cache($chatId, $chat);
            return $chat;

        } catch (\Exception $ex) {
            Log::error($ex);
            if ($throw_error) return ApiResponse::error(ApiResponse::ERR_CHAT_SERVER);
            else return null;
        }
    }

    /**
     * @param $uid
     * @param array $data
     */
    public static function updateChatInfo($uid, array $data) {

        $chatId = Chat::getChatId('u'.$uid);
        $chat = Chat::cache($chatId);
        if ($chat) {
            Chat::cache($chatId, [
                'id' => $chat['id'],
                'name' => ($data['nickname']?:mobile_hidden(substr($data['mobile'], 0, 11)))?:$data['id'],
                'avatar' => $data['avatar']?:self::defaultAvatar(),
                'token' => $chat['token'],
            ]);
        }
    }

    /**
     * 生成用户技能等级数据
     *
     * @param $uid
     */
    public static function set_user_ability($uid) {
        $re = Db::query('select exists(select * from user_ability where ability_user=:uid) e',['uid'=>$uid]);
        if ($re[0]['e'] ?? false) {
            return;
        }
        // 获取课程分类数据
        $curriculum_class = Db::table('curriculum_class')->select();
        $data = [];
        foreach ($curriculum_class as $key=>$val) {
            $data[] = [
                'ability_user' => intval($uid), // 用户id
                'ability_curriculum_class' => $val['class_id'], // 课程分类
                'ability_level' => 1 // 用户技能等级，默认初级 1=初级 2=中级 3=高级
            ];
        }
        Db::table('user_ability')->insertAll($data);
    }

    /**
     * get_user_ability
     * 获取当前登录用户技能等级数据
     *
     * @author zhengkai
     * @date 2017-08-24
     *
     * @return \think\response\Json
     */
    public function get_user_ability($uid)
    {
        // 获取用户技能等级数据
        $ability_data = Db::table('user_ability')
            ->alias('ua')
            ->join('curriculum_class cc', 'ua.ability_curriculum_class=cc.class_id', 'LEFT')
            ->where('ua.ability_user', $uid)
            ->field('cc.class_id, cc.class_name, ua.ability_level')
            ->select();
        $ability = [];
        foreach ($ability_data as $ua_key=>$ua_val) {
            $ability[] = [
                'ability_name' => $ua_val['class_name'],
                'ability_level' => $ua_val['ability_level']
            ];
        }

        // 获取用户已购买课程数据
        $buy_curriculum_total = Db::table('user_buy_curriculum')->where('uc_user', $uid)->count('uc_id');

        // 获取用户信息
        $user_data = $this->where('id', $uid)->find();

        $result = [
            'user_id' => $user_data['id'], // 用户id
            'user_nickname' => ($user_data['nickname']?:mobile_hidden(substr($user_data['mobile'], 0, 11)))?:$user_data['id'], // 用户昵称
            'user_buy_curriculum_total' => $buy_curriculum_total, // 用户已购买课程数据
            'greeting' => time_greet(), // 问候语
            'user_ability' => $ability // 用户技能等级
        ];

        return json(array('code'=>200, 'msg'=>'success', 'data'=>$result));
    }

    /**
     * real_name_auth
     * 实名认证业务处理接口
     *
     * @author zhengkai
     * @date 2017-10-30
     *
     * @param int $uid 用户id
     * @param string $cardNo 身份证号码
     * @param string $realName  真实姓名
     * @return \think\response\Json
     */
    public function real_name_auth($uid, $cardNo, $realName)
    {

        // 查询实名认证数据是否存在
        $sql = <<<SQL
select count(id) as total from real_name_authentication where identity_card_number='{$cardNo}'
SQL;
        $query = Db::query($sql);
        if ($query[0]['total']) return json(array('code'=>1012, 'msg'=>'该身份证已被绑定！', 'data'=>(object)[]));

        $apiUrl = 'http://apis.haoservice.com/idcard/VerifyIdcard';

        $curl = new Curl();
        $curl->get($apiUrl, ['cardNo'=>$cardNo, 'realName'=>$realName, 'key'=>'09e8fb97d2164cbebe9c72b5c37a3f87']);
        $curlResult = $curl->response;
        $data = json_decode($curlResult, true);
        $data = $data['result'];

        if ($data['isok']) {
            $arr = [
                'user_id' => $uid,
                'realname' => $data['realname'],
                'identity_card_number' => $data['idcard'],
                'auth_status' => 'true',
                'auth_time' => time()
            ];

            Db::table('real_name_authentication')->insert($arr);

            self::creditTask($uid,UserCreditRecord::CHANGE_TYPE_REAL_NAME);

            return json(array('code'=>200, 'msg'=>'实名认证成功！', 'data'=>[
                'user_realname' => $arr['realname'],
                'user_cardno' => substr($arr['identity_card_number'],0,3).'*****'.substr($arr['identity_card_number'],strlen($arr['identity_card_number'])-2, strlen($arr['identity_card_number']))
            ]));
        } else {
            return json(array('code'=>1012, 'msg'=>'实名认证失败！', 'data'=>(object)[]));
        }
    }

    /**
     * 增减用户积分
     *
     * @param int $uid
     * @param int $amount
     */
    public static function updateCredit($uid, $amount) {
        Db::execute('UPDATE users SET credit=credit+:amount WHERE id=:uid', ['uid' => $uid, 'amount' => $amount]);
    }

    /**
     * 消费扣除积分
     *
     * @param $uid
     * @param $type
     * @param $amount
     * @param $remark
     * @param array|null $ext
     */
    public static function consumeCredit($uid, $type, $amount, $remark, array $ext = null) {
        self::updateCredit($uid, -$amount);
        UserCreditRecord::record($uid, $type, -$amount, $remark, $ext);
    }

    /**
     * 积分任务更新积分
     *
     * @param $uid
     * @param $type
     * @param null $params
     * @return bool
     */
    public static function creditTask($uid, $type, $params = null) {
        try{
            $task = UserCreditRecord::getTaskBean($type, $uid, $params);

            if ($task->finished() == false) {
                $task->execute();
                self::updateCredit($uid, intval($task['amount']));
                return $task['amount'];
            }

        }catch (\Exception $ex){
            Log::error('积分任务出错[Users::creditTask]：'.$ex->getCode().' => '.$ex->getMessage());
        }
        return false;
    }

    /**
     * 用户每日签到
     *
     * @param $uid
     */
    public static function attend($uid) {
        Db::execute('INSERT INTO user_daily_attendance (uid) VALUES (:uid)',['uid' => $uid]);
    }

    /**
     * 检查每日签到
     *
     * @param $uid
     * @param $date
     * @return bool
     */
    public static function checkAttendance($uid, $date) {
        $sql = <<<SQL
SELECT exists(
  SELECT 1 FROM user_daily_attendance WHERE uid=:uid AND daily=:daily LIMIT 1
) e
SQL;
        $re = Db::query($sql, ['uid' => $uid, 'daily' => $date]);
        return $re[0]['e'] ?? false;
    }

    /**
     * getBaseInfo
     * 获取用户基本信息
     *
     * @author zhengkai
     * @date 2018-01-16
     *
     * @param int $uid 用户id
     * @return null|static
     */
    public static function getBaseInfo($uid)
    {
        $data = self::get(function ($query) use (&$uid, &$field) {
            $query
                // ->field('id, mobile, nickname, avatar, level, gender')
                ->where('id', $uid);
        });

        $data->nickname = ($data->nickname?:mobile_hidden(substr($data->mobile, 0, 11)))?:$data->id;
        $data->avatar = $data->avatar?:self::defaultAvatar();
        $data->level = self::getUserLevelName($data->level);
        $data->gender = ($data->gender==1)?'男':($data->gender==2?'女':'');

        return $data;
    }

    /**
     * getCredit
     * 获取用户可用积分
     *
     * @author zhengkai
     * @date 2018-03-02
     *
     * @param $uid
     * @return int
     */
    public static function getCredit($uid)
    {
        $data = self::get(function ($query) use (&$uid) {
            $query->where('id', $uid);
        });

        return $data->credit;
    }

    /**
     * checkCreditAmount
     * 使用用户积分时检测用户积分是否足够
     *
     * @author zhengkai
     * @date 2018-03-01
     *
     * @param $uid
     * @param $useCredit
     * @return bool
     */
    public static function checkCreditAmount($uid, $useCredit)
    {
        $data = self::get(function ($query) use (&$uid) {
            $query->where('id', $uid);
        });

        $userCredit = $data->credit;

        if ($userCredit < $useCredit) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * findByExtensionCode
     * 根据推广员邀请码查询推广员信息
     *
     * @author wangxuejiao
     * @date 2018-04-11
     *
     * @param int $code 推广员邀请码
     * @return static
     */
    public static function findByExtensionCode($extension_code)
    {
        return  self::where('extension_code', $extension_code)->find();
    }

    /**
     * updateForExtensionCode
     * 根据推广员邀请码查询推广员信息
     *
     * @author wangxuejiao
     * @date 2018-04-11
     *
     * @param int $code 推广员邀请码
     * @return \think\response\Json|false
     */
    public static function updateForExtensionCode($id,$extension_code)
    {
        return self::where('id', $id)->update(['extension_code'=>$extension_code]);
    }

    /**
     * infoNew
     * 获取用户基础信息
     *
     * @author wangxuejiao
     * @date 2018-04-12
     *
     * @param $uid
     * @return array|false|\PDOStatement|string|Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function infoNew($uid) {
        $data=self::where('id',$uid)->field('id as uid,mobile,nickname,avatar,gender,credit,openid,extension_code')->find();
        if(!$data) return [];
        $data=$data->toArray();
        if (empty($data['avatar'])) $data['avatar'] = Users::defaultAvatar();
        $data['nickname'] = ($data['nickname']?:mobile_hidden(substr($data['mobile'], 0, 11)))?:$data['uid'];
        if(empty($data['extension_code'])){
            $data['extension_code']=IntConvert::toString($data['uid']);
            Users::updateForExtensionCode($data['uid'], $data['extension_code']);
        }
        $data['invite_url'] = AgencySalesman::getInviteUrl($data['extension_code']);
        return $data;
    }

    /**
     *  invitedUserCount
     * 获取'我'邀请的用户总数
     *
     * @author wangxuejiao
     * @date 2018-04-12
     *
     * @param array $condition
     * @return int|string
     */
    public static function invitedUserCount($condition=[]){
        return self::where($condition)->count();
    }

    /**
     * invitedUserCount
     * 获取'我'邀请的用户列表
     *
     * @author wangxuejiao
     * @date 2018-04-12
     *
     * @param array $condition
     * @param int $page
     * @param int $limit
     * @param string $order
     * @param string $filed
     * @return array
     * @throws \think\exception\DbException
     */
    public static function invitedUserList($condition=[],$page=1,$limit=10,$order='regtime desc',$filed='*'){
        return self::where($condition)->field($filed)->page($page,$limit)->order($order)->select();
    }

    public static function findOne($condition=[],$filed='*'){
        return self::where($condition)->find();
    }

    public static function updateArray($id,array $data){
        return self::where('id', $id)->update($data);
    }

    public static function getCompanyUser($conditon=[],$rows=10,$field='*'){
        return self::where($conditon)->field($field)->paginate($rows)->toArray();
    }
}